package repositorys

import (
	"errors"
	"github.com/zhongshaofa/swan-jobs/internal/models"
	"github.com/zhongshaofa/swan-jobs/internal/plugin"
	"github.com/zhongshaofa/swan-jobs/internal/request"
	"gorm.io/gorm"
)

type UserInterface interface {
	UserLogin(username string, password string) (*models.User, error)
	Create(user *models.User) (*models.User, error)
	Update(user *models.User) error
	Detail(userId int) (*models.User, error)
	GetList(whereTask *models.User, pagination request.PaginationRequest) ([]*models.User, int, error)
	Delete(ids []int) error
	ApplicationList(userId int) (*models.User, error)
	ApplicationAuth(userId int, applicationIds []int) error
}

type UserRepository struct {
}

func (*UserRepository) UserLogin(username string, password string) (*models.User, error) {
	user := models.User{}

	result := plugin.DB.
		Where("username = ?", username).
		Where("password = ?", password).
		Where("status = ?", models.True).
		First(&user)

	if result.Error != nil {
		return nil, result.Error
	}

	return &user, nil
}

func (*UserRepository) Create(user *models.User) (*models.User, error) {
	var count int64
	plugin.DB.Model(&models.User{}).Where("username = ?", user.Username).Count(&count)
	if count > 0 {
		return nil, errors.New("用户已存在")
	}

	result := plugin.DB.Create(&user)

	return user, result.Error
}

func (receiver UserRepository) GetList(where *models.User, pagination request.PaginationRequest) ([]*models.User, int, error) {
	var list []*models.User

	db := plugin.DB
	db = receiver.buildQuery(where, db).
		Limit(pagination.Limit).
		Offset((pagination.Page - 1) * pagination.Limit)
	result := db.Find(&list)

	var count int64
	receiver.buildQuery(where, db).Count(&count)

	if result.Error != nil {
		return nil, 0, result.Error
	}

	return list, int(count), nil
}

func (UserRepository) Update(user *models.User) error {
	result := plugin.DB.Save(&user)
	return result.Error
}

func (receiver UserRepository) Detail(userId int) (*models.User, error) {
	user := models.User{}
	result := plugin.DB.First(&user, userId)
	if result.Error != nil {
		return nil, result.Error
	}
	return &user, nil
}

func (receiver UserRepository) Delete(ids []int) error {
	result := plugin.DB.Delete(&models.User{}, ids)
	if result.Error != nil {
		return result.Error
	}
	return nil
}

func (receiver UserRepository) SwitchStatus(ids []int, status int) error {
	result := plugin.DB.Model(&models.User{}).
		Where("id in (?)", ids).
		Update("status", status)
	if result.Error != nil {
		return result.Error
	}
	return nil
}

func (receiver UserRepository) ApplicationAuth(userId int, applicationIds []int) error {
	var insertList []*models.UserApplication
	for _, appId := range applicationIds {
		insertList = append(insertList, &models.UserApplication{UserId: userId, AppId: appId})
	}
	err := plugin.DB.Transaction(func(tx *gorm.DB) error {
		if err := tx.Where("user_id = ?", userId).Delete(&models.UserApplication{}).Error; err != nil {
			return err
		}
		if err := tx.Create(&insertList).Error; err != nil {
			return err
		}
		return nil
	})
	return err
}

func (receiver UserRepository) ApplicationList(userId int) (*models.User, error) {
	user := models.User{}
	result := plugin.DB.Preload("ApplicationList.Application").First(&user, userId)
	if result.Error != nil {
		return nil, result.Error
	}
	return &user, nil
}

func (UserRepository) buildQuery(where *models.User, db *gorm.DB) *gorm.DB {
	if len(where.Username) > 0 {
		db = db.Where("username like ?", where.Username+"%")
	}
	if where.ID > 0 {
		db = db.Where("id = ?", where.ID)
	}
	if where.Status > 0 {
		db = db.Where("status = ?", where.Status)
	}
	if where.RoleType > 0 {
		db = db.Where("role_type = ?", where.RoleType)
	}
	return db
}
